/**
 * dat-gui JavaScript Controller Library
 * http://code.google.com/p/dat-gui
 *
 * Copyright 2011 Data Arts Team, Google Creative Lab
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 */

function ___$insertStyle(css) {

  if (!css) {

    return;

  }
  if (typeof window === 'undefined') {

    return;

  }

  var style = document.createElement('style');

  style.setAttribute('type', 'text/css');
  style.innerHTML = css;
  document.head.appendChild(style);

  return css;

}

function colorToString(color, forceCSSHex) {

  var colorFormat = color.__state.conversionName.toString();
  var r = Math.round(color.r);
  var g = Math.round(color.g);
  var b = Math.round(color.b);
  var a = color.a;
  var h = Math.round(color.h);
  var s = color.s.toFixed(1);
  var v = color.v.toFixed(1);
  if (forceCSSHex || colorFormat === 'THREE_CHAR_HEX' || colorFormat === 'SIX_CHAR_HEX') {

    var str = color.hex.toString(16);
    while (str.length < 6) {

      str = '0' + str;

    }
    return '#' + str;

  } else if (colorFormat === 'CSS_RGB') {

    return 'rgb(' + r + ',' + g + ',' + b + ')';

  } else if (colorFormat === 'CSS_RGBA') {

    return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';

  } else if (colorFormat === 'HEX') {

    return '0x' + color.hex.toString(16);

  } else if (colorFormat === 'RGB_ARRAY') {

    return '[' + r + ',' + g + ',' + b + ']';

  } else if (colorFormat === 'RGBA_ARRAY') {

    return '[' + r + ',' + g + ',' + b + ',' + a + ']';

  } else if (colorFormat === 'RGB_OBJ') {

    return '{r:' + r + ',g:' + g + ',b:' + b + '}';

  } else if (colorFormat === 'RGBA_OBJ') {

    return '{r:' + r + ',g:' + g + ',b:' + b + ',a:' + a + '}';

  } else if (colorFormat === 'HSV_OBJ') {

    return '{h:' + h + ',s:' + s + ',v:' + v + '}';

  } else if (colorFormat === 'HSVA_OBJ') {

    return '{h:' + h + ',s:' + s + ',v:' + v + ',a:' + a + '}';

  }
  return 'unknown format';

}

var ARR_EACH = Array.prototype.forEach;
var ARR_SLICE = Array.prototype.slice;
var Common = {
  BREAK: {},
  extend: function extend(target) {

    this.each(ARR_SLICE.call(arguments, 1), function (obj) {

      var keys = this.isObject(obj) ? Object.keys(obj) : [];
      keys.forEach(function (key) {

        if (!this.isUndefined(obj[key])) {

          target[key] = obj[key];

        }

      }.bind(this));

    }, this);
    return target;

  },
  defaults: function defaults(target) {

    this.each(ARR_SLICE.call(arguments, 1), function (obj) {

      var keys = this.isObject(obj) ? Object.keys(obj) : [];
      keys.forEach(function (key) {

        if (this.isUndefined(target[key])) {

          target[key] = obj[key];

        }

      }.bind(this));

    }, this);
    return target;

  },
  compose: function compose() {

    var toCall = ARR_SLICE.call(arguments);
    return function () {

      var args = ARR_SLICE.call(arguments);
      for (var i = toCall.length - 1; i >= 0; i--) {

        args = [toCall[i].apply(this, args)];

      }
      return args[0];

    };

  },
  each: function each(obj, itr, scope) {

    if (!obj) {

      return;

    }
    if (ARR_EACH && obj.forEach && obj.forEach === ARR_EACH) {

      obj.forEach(itr, scope);

    } else if (obj.length === obj.length + 0) {

      var key = void 0;
      var l = void 0;
      for (key = 0, l = obj.length; key < l; key++) {

        if (key in obj && itr.call(scope, obj[key], key) === this.BREAK) {

          return;

        }

      }

    } else {

      for (var _key in obj) {

        if (itr.call(scope, obj[_key], _key) === this.BREAK) {

          return;

        }

      }

    }

  },
  defer: function defer(fnc) {

    setTimeout(fnc, 0);

  },
  debounce: function debounce(func, threshold, callImmediately) {

    var timeout = void 0;
    return function () {

      var obj = this;
      var args = arguments;

      function delayed() {

        timeout = null;
        if (!callImmediately) func.apply(obj, args);

      }

      var callNow = callImmediately || !timeout;
      clearTimeout(timeout);
      timeout = setTimeout(delayed, threshold);
      if (callNow) {

        func.apply(obj, args);

      }

    };

  },
  toArray: function toArray(obj) {

    if (obj.toArray) return obj.toArray();
    return ARR_SLICE.call(obj);

  },
  isUndefined: function isUndefined(obj) {

    return obj === undefined;

  },
  isNull: function isNull(obj) {

    return obj === null;

  },
  isNaN: function (_isNaN) {

    function isNaN() {

      return _isNaN.apply(this, arguments);

    }

    isNaN.toString = function () {

      return _isNaN.toString();

    };
    return isNaN;

  }(function (obj) {

    return isNaN(obj);

  }),
  isArray: Array.isArray || function (obj) {

    return obj.constructor === Array;

  },
  isObject: function isObject(obj) {

    return obj === Object(obj);

  },
  isNumber: function isNumber(obj) {

    return obj === obj + 0;

  },
  isString: function isString(obj) {

    return obj === obj + '';

  },
  isBoolean: function isBoolean(obj) {

    return obj === false || obj === true;

  },
  isFunction: function isFunction(obj) {

    return obj instanceof Function;

  }
};

var INTERPRETATIONS = [
  {
    litmus: Common.isString,
    conversions: {
      THREE_CHAR_HEX: {
        read: function read(original) {

          var test = original.match(/^#([A-F0-9])([A-F0-9])([A-F0-9])$/i);
          if (test === null) {

            return false;

          }
          return {
            space: 'HEX',
            hex: parseInt('0x' + test[1].toString() + test[1].toString() + test[2].toString() + test[2].toString() + test[3].toString() + test[3].toString(), 0)
          };

        },
        write: colorToString
      },
      SIX_CHAR_HEX: {
        read: function read(original) {

          var test = original.match(/^#([A-F0-9]{6})$/i);
          if (test === null) {

            return false;

          }
          return {
            space: 'HEX',
            hex: parseInt('0x' + test[1].toString(), 0)
          };

        },
        write: colorToString
      },
      CSS_RGB: {
        read: function read(original) {

          var test = original.match(/^rgb\(\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*\)/);
          if (test === null) {

            return false;

          }
          return {
            space: 'RGB',
            r: parseFloat(test[1]),
            g: parseFloat(test[2]),
            b: parseFloat(test[3])
          };

        },
        write: colorToString
      },
      CSS_RGBA: {
        read: function read(original) {

          var test = original.match(/^rgba\(\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*\)/);
          if (test === null) {

            return false;

          }
          return {
            space: 'RGB',
            r: parseFloat(test[1]),
            g: parseFloat(test[2]),
            b: parseFloat(test[3]),
            a: parseFloat(test[4])
          };

        },
        write: colorToString
      }
    }
  },
  {
    litmus: Common.isNumber,
    conversions: {
      HEX: {
        read: function read(original) {

          return {
            space: 'HEX',
            hex: original,
            conversionName: 'HEX'
          };

        },
        write: function write(color) {

          return color.hex;

        }
      }
    }
  },
  {
    litmus: Common.isArray,
    conversions: {
      RGB_ARRAY: {
        read: function read(original) {

          if (original.length !== 3) {

            return false;

          }
          return {
            space: 'RGB',
            r: original[0],
            g: original[1],
            b: original[2]
          };

        },
        write: function write(color) {

          return [color.r, color.g, color.b];

        }
      },
      RGBA_ARRAY: {
        read: function read(original) {

          if (original.length !== 4) return false;
          return {
            space: 'RGB',
            r: original[0],
            g: original[1],
            b: original[2],
            a: original[3]
          };

        },
        write: function write(color) {

          return [color.r, color.g, color.b, color.a];

        }
      }
    }
  },
  {
    litmus: Common.isObject,
    conversions: {
      RGBA_OBJ: {
        read: function read(original) {

          if (Common.isNumber(original.r) && Common.isNumber(original.g) && Common.isNumber(original.b) && Common.isNumber(original.a)) {

            return {
              space: 'RGB',
              r: original.r,
              g: original.g,
              b: original.b,
              a: original.a
            };

          }
          return false;

        },
        write: function write(color) {

          return {
            r: color.r,
            g: color.g,
            b: color.b,
            a: color.a
          };

        }
      },
      RGB_OBJ: {
        read: function read(original) {

          if (Common.isNumber(original.r) && Common.isNumber(original.g) && Common.isNumber(original.b)) {

            return {
              space: 'RGB',
              r: original.r,
              g: original.g,
              b: original.b
            };

          }
          return false;

        },
        write: function write(color) {

          return {
            r: color.r,
            g: color.g,
            b: color.b
          };

        }
      },
      HSVA_OBJ: {
        read: function read(original) {

          if (Common.isNumber(original.h) && Common.isNumber(original.s) && Common.isNumber(original.v) && Common.isNumber(original.a)) {

            return {
              space: 'HSV',
              h: original.h,
              s: original.s,
              v: original.v,
              a: original.a
            };

          }
          return false;

        },
        write: function write(color) {

          return {
            h: color.h,
            s: color.s,
            v: color.v,
            a: color.a
          };

        }
      },
      HSV_OBJ: {
        read: function read(original) {

          if (Common.isNumber(original.h) && Common.isNumber(original.s) && Common.isNumber(original.v)) {

            return {
              space: 'HSV',
              h: original.h,
              s: original.s,
              v: original.v
            };

          }
          return false;

        },
        write: function write(color) {

          return {
            h: color.h,
            s: color.s,
            v: color.v
          };

        }
      }
    }
  }];
var result = void 0;
var toReturn = void 0;
var interpret = function interpret() {

  toReturn = false;
  var original = arguments.length > 1 ? Common.toArray(arguments) : arguments[0];
  Common.each(INTERPRETATIONS, function (family) {

    if (family.litmus(original)) {

      Common.each(family.conversions, function (conversion, conversionName) {

        result = conversion.read(original);
        if (toReturn === false && result !== false) {

          toReturn = result;
          result.conversionName = conversionName;
          result.conversion = conversion;
          return Common.BREAK;

        }

      });
      return Common.BREAK;

    }

  });
  return toReturn;

};

var tmpComponent = void 0;
var ColorMath = {
  hsv_to_rgb: function hsv_to_rgb(h, s, v) {

    var hi = Math.floor(h / 60) % 6;
    var f = h / 60 - Math.floor(h / 60);
    var p = v * (1.0 - s);
    var q = v * (1.0 - f * s);
    var t = v * (1.0 - (1.0 - f) * s);
    var c = [[v, t, p], [q, v, p], [p, v, t], [p, q, v], [t, p, v], [v, p, q]][hi];
    return {
      r: c[0] * 255,
      g: c[1] * 255,
      b: c[2] * 255
    };

  },
  rgb_to_hsv: function rgb_to_hsv(r, g, b) {

    var min = Math.min(r, g, b);
    var max = Math.max(r, g, b);
    var delta = max - min;
    var h = void 0;
    var s = void 0;
    if (max !== 0) {

      s = delta / max;

    } else {

      return {
        h: NaN,
        s: 0,
        v: 0
      };

    }
    if (r === max) {

      h = (g - b) / delta;

    } else if (g === max) {

      h = 2 + (b - r) / delta;

    } else {

      h = 4 + (r - g) / delta;

    }
    h /= 6;
    if (h < 0) {

      h += 1;

    }
    return {
      h: h * 360,
      s: s,
      v: max / 255
    };

  },
  rgb_to_hex: function rgb_to_hex(r, g, b) {

    var hex = this.hex_with_component(0, 2, r);
    hex = this.hex_with_component(hex, 1, g);
    hex = this.hex_with_component(hex, 0, b);
    return hex;

  },
  component_from_hex: function component_from_hex(hex, componentIndex) {

    return hex >> componentIndex * 8 & 0xFF;

  },
  hex_with_component: function hex_with_component(hex, componentIndex, value) {

    return value << (tmpComponent = componentIndex * 8) | hex & ~(0xFF << tmpComponent);

  }
};

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {

  return typeof obj;

} : function (obj) {

  return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;

};


var classCallCheck = function (instance, Constructor) {

  if (!(instance instanceof Constructor)) {

    throw new TypeError("Cannot call a class as a function");

  }

};

var createClass = function () {

  function defineProperties(target, props) {

    for (var i = 0; i < props.length; i++) {

      var descriptor = props[i];
      descriptor.enumerable = descriptor.enumerable || false;
      descriptor.configurable = true;
      if ("value" in descriptor) descriptor.writable = true;
      Object.defineProperty(target, descriptor.key, descriptor);

    }

  }

  return function (Constructor, protoProps, staticProps) {

    if (protoProps) defineProperties(Constructor.prototype, protoProps);
    if (staticProps) defineProperties(Constructor, staticProps);
    return Constructor;

  };

}();


var get = function get(object, property, receiver) {

  if (object === null) object = Function.prototype;
  var desc = Object.getOwnPropertyDescriptor(object, property);

  if (desc === undefined) {

    var parent = Object.getPrototypeOf(object);

    if (parent === null) {

      return undefined;

    } else {

      return get(parent, property, receiver);

    }

  } else if ("value" in desc) {

    return desc.value;

  } else {

    var getter = desc.get;

    if (getter === undefined) {

      return undefined;

    }

    return getter.call(receiver);

  }

};

var inherits = function (subClass, superClass) {

  if (typeof superClass !== "function" && superClass !== null) {

    throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);

  }

  subClass.prototype = Object.create(superClass && superClass.prototype, {
    constructor: {
      value: subClass,
      enumerable: false,
      writable: true,
      configurable: true
    }
  });
  if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;

};


var possibleConstructorReturn = function (self, call) {

  if (!self) {

    throw new ReferenceError("this hasn't been initialised - super() hasn't been called");

  }

  return call && (typeof call === "object" || typeof call === "function") ? call : self;

};

var Color = function () {

  function Color() {

    classCallCheck(this, Color);
    this.__state = interpret.apply(this, arguments);
    if (this.__state === false) {

      throw new Error('Failed to interpret color arguments');

    }
    this.__state.a = this.__state.a || 1;

  }

  createClass(Color, [{
    key: 'toString',
    value: function toString() {

      return colorToString(this);

    }
  }, {
    key: 'toHexString',
    value: function toHexString() {

      return colorToString(this, true);

    }
  }, {
    key: 'toOriginal',
    value: function toOriginal() {

      return this.__state.conversion.write(this);

    }
  }]);
  return Color;

}();

function defineRGBComponent(target, component, componentHexIndex) {

  Object.defineProperty(target, component, {
    get: function get$$1() {

      if (this.__state.space === 'RGB') {

        return this.__state[component];

      }
      Color.recalculateRGB(this, component, componentHexIndex);
      return this.__state[component];

    },
    set: function set$$1(v) {

      if (this.__state.space !== 'RGB') {

        Color.recalculateRGB(this, component, componentHexIndex);
        this.__state.space = 'RGB';

      }
      this.__state[component] = v;

    }
  });

}

function defineHSVComponent(target, component) {

  Object.defineProperty(target, component, {
    get: function get$$1() {

      if (this.__state.space === 'HSV') {

        return this.__state[component];

      }
      Color.recalculateHSV(this);
      return this.__state[component];

    },
    set: function set$$1(v) {

      if (this.__state.space !== 'HSV') {

        Color.recalculateHSV(this);
        this.__state.space = 'HSV';

      }
      this.__state[component] = v;

    }
  });

}

Color.recalculateRGB = function (color, component, componentHexIndex) {

  if (color.__state.space === 'HEX') {

    color.__state[component] = ColorMath.component_from_hex(color.__state.hex, componentHexIndex);

  } else if (color.__state.space === 'HSV') {

    Common.extend(color.__state, ColorMath.hsv_to_rgb(color.__state.h, color.__state.s, color.__state.v));

  } else {

    throw new Error('Corrupted color state');

  }

};
Color.recalculateHSV = function (color) {

  var result = ColorMath.rgb_to_hsv(color.r, color.g, color.b);
  Common.extend(color.__state, {
    s: result.s,
    v: result.v
  });
  if (!Common.isNaN(result.h)) {

    color.__state.h = result.h;

  } else if (Common.isUndefined(color.__state.h)) {

    color.__state.h = 0;

  }

};
Color.COMPONENTS = ['r', 'g', 'b', 'h', 's', 'v', 'hex', 'a'];
defineRGBComponent(Color.prototype, 'r', 2);
defineRGBComponent(Color.prototype, 'g', 1);
defineRGBComponent(Color.prototype, 'b', 0);
defineHSVComponent(Color.prototype, 'h');
defineHSVComponent(Color.prototype, 's');
defineHSVComponent(Color.prototype, 'v');
Object.defineProperty(Color.prototype, 'a', {
  get: function get$$1() {

    return this.__state.a;

  },
  set: function set$$1(v) {

    this.__state.a = v;

  }
});
Object.defineProperty(Color.prototype, 'hex', {
  get: function get$$1() {

    if (this.__state.space !== 'HEX') {

      this.__state.hex = ColorMath.rgb_to_hex(this.r, this.g, this.b);
      this.__state.space = 'HEX';

    }
    return this.__state.hex;

  },
  set: function set$$1(v) {

    this.__state.space = 'HEX';
    this.__state.hex = v;

  }
});

var Controller = function () {

  function Controller(object, property) {

    classCallCheck(this, Controller);
    this.initialValue = object[property];
    this.domElement = document.createElement('div');
    this.object = object;
    this.property = property;
    this.__onChange = undefined;
    this.__onFinishChange = undefined;

  }

  createClass(Controller, [{
    key: 'onChange',
    value: function onChange(fnc) {

      this.__onChange = fnc;
      return this;

    }
  }, {
    key: 'onFinishChange',
    value: function onFinishChange(fnc) {

      this.__onFinishChange = fnc;
      return this;

    }
  }, {
    key: 'setValue',
    value: function setValue(newValue) {

      this.object[this.property] = newValue;
      if (this.__onChange) {

        this.__onChange.call(this, newValue);

      }
      this.updateDisplay();
      return this;

    }
  }, {
    key: 'getValue',
    value: function getValue() {

      return this.object[this.property];

    }
  }, {
    key: 'updateDisplay',
    value: function updateDisplay() {

      return this;

    }
  }, {
    key: 'isModified',
    value: function isModified() {

      return this.initialValue !== this.getValue();

    }
  }]);
  return Controller;

}();

var EVENT_MAP = {
  HTMLEvents: ['change'],
  MouseEvents: ['click', 'mousemove', 'mousedown', 'mouseup', 'mouseover'],
  KeyboardEvents: ['keydown']
};
var EVENT_MAP_INV = {};
Common.each(EVENT_MAP, function (v, k) {

  Common.each(v, function (e) {

    EVENT_MAP_INV[e] = k;

  });

});
var CSS_VALUE_PIXELS = /(\d+(\.\d+)?)px/;

function cssValueToPixels(val) {

  if (val === '0' || Common.isUndefined(val)) {

    return 0;

  }
  var match = val.match(CSS_VALUE_PIXELS);
  if (!Common.isNull(match)) {

    return parseFloat(match[1]);

  }
  return 0;

}

var dom = {
  makeSelectable: function makeSelectable(elem, selectable) {

    if (elem === undefined || elem.style === undefined) return;
    elem.onselectstart = selectable ? function () {

      return false;

    } : function () {
    };
    elem.style.MozUserSelect = selectable ? 'auto' : 'none';
    elem.style.KhtmlUserSelect = selectable ? 'auto' : 'none';
    elem.unselectable = selectable ? 'on' : 'off';

  },
  makeFullscreen: function makeFullscreen(elem, hor, vert) {

    var vertical = vert;
    var horizontal = hor;
    if (Common.isUndefined(horizontal)) {

      horizontal = true;

    }
    if (Common.isUndefined(vertical)) {

      vertical = true;

    }
    elem.style.position = 'absolute';
    if (horizontal) {

      elem.style.left = 0;
      elem.style.right = 0;

    }
    if (vertical) {

      elem.style.top = 0;
      elem.style.bottom = 0;

    }

  },
  fakeEvent: function fakeEvent(elem, eventType, pars, aux) {

    var params = pars || {};
    var className = EVENT_MAP_INV[eventType];
    if (!className) {

      throw new Error('Event type ' + eventType + ' not supported.');

    }
    var evt = document.createEvent(className);
    switch (className) {

      case 'MouseEvents': {

        var clientX = params.x || params.clientX || 0;
        var clientY = params.y || params.clientY || 0;
        evt.initMouseEvent(eventType, params.bubbles || false, params.cancelable || true, window, params.clickCount || 1, 0,
          0,
          clientX,
          clientY,
          false, false, false, false, 0, null);
        break;

      }
      case 'KeyboardEvents': {

        var init = evt.initKeyboardEvent || evt.initKeyEvent;
        Common.defaults(params, {
          cancelable: true,
          ctrlKey: false,
          altKey: false,
          shiftKey: false,
          metaKey: false,
          keyCode: undefined,
          charCode: undefined
        });
        init(eventType, params.bubbles || false, params.cancelable, window, params.ctrlKey, params.altKey, params.shiftKey, params.metaKey, params.keyCode, params.charCode);
        break;

      }
      default: {

        evt.initEvent(eventType, params.bubbles || false, params.cancelable || true);
        break;

      }

    }
    Common.defaults(evt, aux);
    elem.dispatchEvent(evt);

  },
  bind: function bind(elem, event, func, newBool) {

    var bool = newBool || false;
    if (elem.addEventListener) {

      elem.addEventListener(event, func, bool);

    } else if (elem.attachEvent) {

      elem.attachEvent('on' + event, func);

    }
    return dom;

  },
  unbind: function unbind(elem, event, func, newBool) {

    var bool = newBool || false;
    if (elem.removeEventListener) {

      elem.removeEventListener(event, func, bool);

    } else if (elem.detachEvent) {

      elem.detachEvent('on' + event, func);

    }
    return dom;

  },
  addClass: function addClass(elem, className) {

    if (elem.className === undefined) {

      elem.className = className;

    } else if (elem.className !== className) {

      var classes = elem.className.split(/ +/);
      if (classes.indexOf(className) === -1) {

        classes.push(className);
        elem.className = classes.join(' ').replace(/^\s+/, '').replace(/\s+$/, '');

      }

    }
    return dom;

  },
  removeClass: function removeClass(elem, className) {

    if (className) {

      if (elem.className === className) {

        elem.removeAttribute('class');

      } else {

        var classes = elem.className.split(/ +/);
        var index = classes.indexOf(className);
        if (index !== -1) {

          classes.splice(index, 1);
          elem.className = classes.join(' ');

        }

      }

    } else {

      elem.className = undefined;

    }
    return dom;

  },
  hasClass: function hasClass(elem, className) {

    return new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)').test(elem.className) || false;

  },
  getWidth: function getWidth(elem) {

    var style = getComputedStyle(elem);
    return cssValueToPixels(style['border-left-width']) + cssValueToPixels(style['border-right-width']) + cssValueToPixels(style['padding-left']) + cssValueToPixels(style['padding-right']) + cssValueToPixels(style.width);

  },
  getHeight: function getHeight(elem) {

    var style = getComputedStyle(elem);
    return cssValueToPixels(style['border-top-width']) + cssValueToPixels(style['border-bottom-width']) + cssValueToPixels(style['padding-top']) + cssValueToPixels(style['padding-bottom']) + cssValueToPixels(style.height);

  },
  getOffset: function getOffset(el) {

    var elem = el;
    var offset = {left: 0, top: 0};
    if (elem.offsetParent) {

      do {

        offset.left += elem.offsetLeft;
        offset.top += elem.offsetTop;
        elem = elem.offsetParent;

      } while (elem);

    }
    return offset;

  },
  isActive: function isActive(elem) {

    return elem === document.activeElement && (elem.type || elem.href);

  }
};

var BooleanController = function (_Controller) {

  inherits(BooleanController, _Controller);

  function BooleanController(object, property) {

    classCallCheck(this, BooleanController);
    var _this2 = possibleConstructorReturn(this, (BooleanController.__proto__ || Object.getPrototypeOf(BooleanController)).call(this, object, property));
    var _this = _this2;
    _this2.__prev = _this2.getValue();
    _this2.__checkbox = document.createElement('input');
    _this2.__checkbox.setAttribute('type', 'checkbox');

    function onChange() {

      _this.setValue(!_this.__prev);

    }

    dom.bind(_this2.__checkbox, 'change', onChange, false);
    _this2.domElement.appendChild(_this2.__checkbox);
    _this2.updateDisplay();
    return _this2;

  }

  createClass(BooleanController, [{
    key: 'setValue',
    value: function setValue(v) {

      var toReturn = get(BooleanController.prototype.__proto__ || Object.getPrototypeOf(BooleanController.prototype), 'setValue', this).call(this, v);
      if (this.__onFinishChange) {

        this.__onFinishChange.call(this, this.getValue());

      }
      this.__prev = this.getValue();
      return toReturn;

    }
  }, {
    key: 'updateDisplay',
    value: function updateDisplay() {

      if (this.getValue() === true) {

        this.__checkbox.setAttribute('checked', 'checked');
        this.__checkbox.checked = true;
        this.__prev = true;

      } else {

        this.__checkbox.checked = false;
        this.__prev = false;

      }
      return get(BooleanController.prototype.__proto__ || Object.getPrototypeOf(BooleanController.prototype), 'updateDisplay', this).call(this);

    }
  }]);
  return BooleanController;

}(Controller);

var OptionController = function (_Controller) {

  inherits(OptionController, _Controller);

  function OptionController(object, property, opts) {

    classCallCheck(this, OptionController);
    var _this2 = possibleConstructorReturn(this, (OptionController.__proto__ || Object.getPrototypeOf(OptionController)).call(this, object, property));
    var options = opts;
    var _this = _this2;
    _this2.__select = document.createElement('select');
    if (Common.isArray(options)) {

      var map = {};
      Common.each(options, function (element) {

        map[element] = element;

      });
      options = map;

    }
    Common.each(options, function (value, key) {

      var opt = document.createElement('option');
      opt.innerHTML = key;
      opt.setAttribute('value', value);
      _this.__select.appendChild(opt);

    });
    _this2.updateDisplay();
    dom.bind(_this2.__select, 'change', function () {

      var desiredValue = this.options[this.selectedIndex].value;
      _this.setValue(desiredValue);

    });
    _this2.domElement.appendChild(_this2.__select);
    return _this2;

  }

  createClass(OptionController, [{
    key: 'setValue',
    value: function setValue(v) {

      var toReturn = get(OptionController.prototype.__proto__ || Object.getPrototypeOf(OptionController.prototype), 'setValue', this).call(this, v);
      if (this.__onFinishChange) {

        this.__onFinishChange.call(this, this.getValue());

      }
      return toReturn;

    }
  }, {
    key: 'updateDisplay',
    value: function updateDisplay() {

      if (dom.isActive(this.__select)) return this;
      this.__select.value = this.getValue();
      return get(OptionController.prototype.__proto__ || Object.getPrototypeOf(OptionController.prototype), 'updateDisplay', this).call(this);

    }
  }]);
  return OptionController;

}(Controller);

var StringController = function (_Controller) {

  inherits(StringController, _Controller);

  function StringController(object, property) {

    classCallCheck(this, StringController);
    var _this2 = possibleConstructorReturn(this, (StringController.__proto__ || Object.getPrototypeOf(StringController)).call(this, object, property));
    var _this = _this2;

    function onChange() {

      _this.setValue(_this.__input.value);

    }

    function onBlur() {

      if (_this.__onFinishChange) {

        _this.__onFinishChange.call(_this, _this.getValue());

      }

    }

    _this2.__input = document.createElement('input');
    _this2.__input.setAttribute('type', 'text');
    dom.bind(_this2.__input, 'keyup', onChange);
    dom.bind(_this2.__input, 'change', onChange);
    dom.bind(_this2.__input, 'blur', onBlur);
    dom.bind(_this2.__input, 'keydown', function (e) {

      if (e.keyCode === 13) {

        this.blur();

      }

    });
    _this2.updateDisplay();
    _this2.domElement.appendChild(_this2.__input);
    return _this2;

  }

  createClass(StringController, [{
    key: 'updateDisplay',
    value: function updateDisplay() {

      if (!dom.isActive(this.__input)) {

        this.__input.value = this.getValue();

      }
      return get(StringController.prototype.__proto__ || Object.getPrototypeOf(StringController.prototype), 'updateDisplay', this).call(this);

    }
  }]);
  return StringController;

}(Controller);

function numDecimals(x) {

  var _x = x.toString();
  if (_x.indexOf('.') > -1) {

    return _x.length - _x.indexOf('.') - 1;

  }
  return 0;

}

var NumberController = function (_Controller) {

  inherits(NumberController, _Controller);

  function NumberController(object, property, params) {

    classCallCheck(this, NumberController);
    var _this = possibleConstructorReturn(this, (NumberController.__proto__ || Object.getPrototypeOf(NumberController)).call(this, object, property));
    var _params = params || {};
    _this.__min = _params.min;
    _this.__max = _params.max;
    _this.__step = _params.step;
    if (Common.isUndefined(_this.__step)) {

      if (_this.initialValue === 0) {

        _this.__impliedStep = 1;

      } else {

        _this.__impliedStep = Math.pow(10, Math.floor(Math.log(Math.abs(_this.initialValue)) / Math.LN10)) / 10;

      }

    } else {

      _this.__impliedStep = _this.__step;

    }
    _this.__precision = numDecimals(_this.__impliedStep);
    return _this;

  }

  createClass(NumberController, [{
    key: 'setValue',
    value: function setValue(v) {

      var _v = v;
      if (this.__min !== undefined && _v < this.__min) {

        _v = this.__min;

      } else if (this.__max !== undefined && _v > this.__max) {

        _v = this.__max;

      }
      if (this.__step !== undefined && _v % this.__step !== 0) {

        _v = Math.round(_v / this.__step) * this.__step;

      }
      return get(NumberController.prototype.__proto__ || Object.getPrototypeOf(NumberController.prototype), 'setValue', this).call(this, _v);

    }
  }, {
    key: 'min',
    value: function min(minValue) {

      this.__min = minValue;
      return this;

    }
  }, {
    key: 'max',
    value: function max(maxValue) {

      this.__max = maxValue;
      return this;

    }
  }, {
    key: 'step',
    value: function step(stepValue) {

      this.__step = stepValue;
      this.__impliedStep = stepValue;
      this.__precision = numDecimals(stepValue);
      return this;

    }
  }]);
  return NumberController;

}(Controller);

function roundToDecimal(value, decimals) {

  var tenTo = Math.pow(10, decimals);
  return Math.round(value * tenTo) / tenTo;

}

var NumberControllerBox = function (_NumberController) {

  inherits(NumberControllerBox, _NumberController);

  function NumberControllerBox(object, property, params) {

    classCallCheck(this, NumberControllerBox);
    var _this2 = possibleConstructorReturn(this, (NumberControllerBox.__proto__ || Object.getPrototypeOf(NumberControllerBox)).call(this, object, property, params));
    _this2.__truncationSuspended = false;
    var _this = _this2;
    var prevY = void 0;

    function onChange() {

      var attempted = parseFloat(_this.__input.value);
      if (!Common.isNaN(attempted)) {

        _this.setValue(attempted);

      }

    }

    function onFinish() {

      if (_this.__onFinishChange) {

        _this.__onFinishChange.call(_this, _this.getValue());

      }

    }

    function onBlur() {

      onFinish();

    }

    function onMouseDrag(e) {

      var diff = prevY - e.clientY;
      _this.setValue(_this.getValue() + diff * _this.__impliedStep);
      prevY = e.clientY;

    }

    function onMouseUp() {

      dom.unbind(window, 'mousemove', onMouseDrag);
      dom.unbind(window, 'mouseup', onMouseUp);
      onFinish();

    }

    function onMouseDown(e) {

      dom.bind(window, 'mousemove', onMouseDrag);
      dom.bind(window, 'mouseup', onMouseUp);
      prevY = e.clientY;

    }

    _this2.__input = document.createElement('input');
    _this2.__input.setAttribute('type', 'text');
    dom.bind(_this2.__input, 'change', onChange);
    dom.bind(_this2.__input, 'blur', onBlur);
    dom.bind(_this2.__input, 'mousedown', onMouseDown);
    dom.bind(_this2.__input, 'keydown', function (e) {

      if (e.keyCode === 13) {

        _this.__truncationSuspended = true;
        this.blur();
        _this.__truncationSuspended = false;
        onFinish();

      }

    });
    _this2.updateDisplay();
    _this2.domElement.appendChild(_this2.__input);
    return _this2;

  }

  createClass(NumberControllerBox, [{
    key: 'updateDisplay',
    value: function updateDisplay() {

      this.__input.value = this.__truncationSuspended ? this.getValue() : roundToDecimal(this.getValue(), this.__precision);
      return get(NumberControllerBox.prototype.__proto__ || Object.getPrototypeOf(NumberControllerBox.prototype), 'updateDisplay', this).call(this);

    }
  }]);
  return NumberControllerBox;

}(NumberController);

function map(v, i1, i2, o1, o2) {

  return o1 + (o2 - o1) * ((v - i1) / (i2 - i1));

}

var NumberControllerSlider = function (_NumberController) {

  inherits(NumberControllerSlider, _NumberController);

  function NumberControllerSlider(object, property, min, max, step) {

    classCallCheck(this, NumberControllerSlider);
    var _this2 = possibleConstructorReturn(this, (NumberControllerSlider.__proto__ || Object.getPrototypeOf(NumberControllerSlider)).call(this, object, property, {min: min, max: max, step: step}));
    var _this = _this2;
    _this2.__background = document.createElement('div');
    _this2.__foreground = document.createElement('div');
    dom.bind(_this2.__background, 'mousedown', onMouseDown);
    dom.bind(_this2.__background, 'touchstart', onTouchStart);
    dom.addClass(_this2.__background, 'slider');
    dom.addClass(_this2.__foreground, 'slider-fg');

    function onMouseDown(e) {

      document.activeElement.blur();
      dom.bind(window, 'mousemove', onMouseDrag);
      dom.bind(window, 'mouseup', onMouseUp);
      onMouseDrag(e);

    }

    function onMouseDrag(e) {

      e.preventDefault();
      var bgRect = _this.__background.getBoundingClientRect();
      _this.setValue(map(e.clientX, bgRect.left, bgRect.right, _this.__min, _this.__max));
      return false;

    }

    function onMouseUp() {

      dom.unbind(window, 'mousemove', onMouseDrag);
      dom.unbind(window, 'mouseup', onMouseUp);
      if (_this.__onFinishChange) {

        _this.__onFinishChange.call(_this, _this.getValue());

      }

    }

    function onTouchStart(e) {

      if (e.touches.length !== 1) {

        return;

      }
      dom.bind(window, 'touchmove', onTouchMove);
      dom.bind(window, 'touchend', onTouchEnd);
      onTouchMove(e);

    }

    function onTouchMove(e) {

      var clientX = e.touches[0].clientX;
      var bgRect = _this.__background.getBoundingClientRect();
      _this.setValue(map(clientX, bgRect.left, bgRect.right, _this.__min, _this.__max));

    }

    function onTouchEnd() {

      dom.unbind(window, 'touchmove', onTouchMove);
      dom.unbind(window, 'touchend', onTouchEnd);
      if (_this.__onFinishChange) {

        _this.__onFinishChange.call(_this, _this.getValue());

      }

    }

    _this2.updateDisplay();
    _this2.__background.appendChild(_this2.__foreground);
    _this2.domElement.appendChild(_this2.__background);
    return _this2;

  }

  createClass(NumberControllerSlider, [{
    key: 'updateDisplay',
    value: function updateDisplay() {

      var pct = (this.getValue() - this.__min) / (this.__max - this.__min);
      this.__foreground.style.width = pct * 100 + '%';
      return get(NumberControllerSlider.prototype.__proto__ || Object.getPrototypeOf(NumberControllerSlider.prototype), 'updateDisplay', this).call(this);

    }
  }]);
  return NumberControllerSlider;

}(NumberController);

var FunctionController = function (_Controller) {

  inherits(FunctionController, _Controller);

  function FunctionController(object, property, text) {

    classCallCheck(this, FunctionController);
    var _this2 = possibleConstructorReturn(this, (FunctionController.__proto__ || Object.getPrototypeOf(FunctionController)).call(this, object, property));
    var _this = _this2;
    _this2.__button = document.createElement('div');
    _this2.__button.innerHTML = text === undefined ? 'Fire' : text;
    dom.bind(_this2.__button, 'click', function (e) {

      e.preventDefault();
      _this.fire();
      return false;

    });
    dom.addClass(_this2.__button, 'button');
    _this2.domElement.appendChild(_this2.__button);
    return _this2;

  }

  createClass(FunctionController, [{
    key: 'fire',
    value: function fire() {

      if (this.__onChange) {

        this.__onChange.call(this);

      }
      this.getValue().call(this.object);
      if (this.__onFinishChange) {

        this.__onFinishChange.call(this, this.getValue());

      }

    }
  }]);
  return FunctionController;

}(Controller);

var ColorController = function (_Controller) {

  inherits(ColorController, _Controller);

  function ColorController(object, property) {

    classCallCheck(this, ColorController);
    var _this2 = possibleConstructorReturn(this, (ColorController.__proto__ || Object.getPrototypeOf(ColorController)).call(this, object, property));
    _this2.__color = new Color(_this2.getValue());
    _this2.__temp = new Color(0);
    var _this = _this2;
    _this2.domElement = document.createElement('div');
    dom.makeSelectable(_this2.domElement, false);
    _this2.__selector = document.createElement('div');
    _this2.__selector.className = 'selector';
    _this2.__saturation_field = document.createElement('div');
    _this2.__saturation_field.className = 'saturation-field';
    _this2.__field_knob = document.createElement('div');
    _this2.__field_knob.className = 'field-knob';
    _this2.__field_knob_border = '2px solid ';
    _this2.__hue_knob = document.createElement('div');
    _this2.__hue_knob.className = 'hue-knob';
    _this2.__hue_field = document.createElement('div');
    _this2.__hue_field.className = 'hue-field';
    _this2.__input = document.createElement('input');
    _this2.__input.type = 'text';
    _this2.__input_textShadow = '0 1px 1px ';
    dom.bind(_this2.__input, 'keydown', function (e) {

      if (e.keyCode === 13) {

        onBlur.call(this);

      }

    });
    dom.bind(_this2.__input, 'blur', onBlur);
    dom.bind(_this2.__selector, 'mousedown', function () {

      dom.addClass(this, 'drag').bind(window, 'mouseup', function () {

        dom.removeClass(_this.__selector, 'drag');

      });

    });
    dom.bind(_this2.__selector, 'touchstart', function () {

      dom.addClass(this, 'drag').bind(window, 'touchend', function () {

        dom.removeClass(_this.__selector, 'drag');

      });

    });
    var valueField = document.createElement('div');
    Common.extend(_this2.__selector.style, {
      width: '122px',
      height: '102px',
      padding: '3px',
      backgroundColor: '#222',
      boxShadow: '0px 1px 3px rgba(0,0,0,0.3)'
    });
    Common.extend(_this2.__field_knob.style, {
      position: 'absolute',
      width: '12px',
      height: '12px',
      border: _this2.__field_knob_border + (_this2.__color.v < 0.5 ? '#fff' : '#000'),
      boxShadow: '0px 1px 3px rgba(0,0,0,0.5)',
      borderRadius: '12px',
      zIndex: 1
    });
    Common.extend(_this2.__hue_knob.style, {
      position: 'absolute',
      width: '15px',
      height: '2px',
      borderRight: '4px solid #fff',
      zIndex: 1
    });
    Common.extend(_this2.__saturation_field.style, {
      width: '100px',
      height: '100px',
      border: '1px solid #555',
      marginRight: '3px',
      display: 'inline-block',
      cursor: 'pointer'
    });
    Common.extend(valueField.style, {
      width: '100%',
      height: '100%',
      background: 'none'
    });
    linearGradient(valueField, 'top', 'rgba(0,0,0,0)', '#000');
    Common.extend(_this2.__hue_field.style, {
      width: '15px',
      height: '100px',
      border: '1px solid #555',
      cursor: 'ns-resize',
      position: 'absolute',
      top: '3px',
      right: '3px'
    });
    hueGradient(_this2.__hue_field);
    Common.extend(_this2.__input.style, {
      outline: 'none',
      textAlign: 'center',
      color: '#fff',
      border: 0,
      fontWeight: 'bold',
      textShadow: _this2.__input_textShadow + 'rgba(0,0,0,0.7)'
    });
    dom.bind(_this2.__saturation_field, 'mousedown', fieldDown);
    dom.bind(_this2.__saturation_field, 'touchstart', fieldDown);
    dom.bind(_this2.__field_knob, 'mousedown', fieldDown);
    dom.bind(_this2.__field_knob, 'touchstart', fieldDown);
    dom.bind(_this2.__hue_field, 'mousedown', fieldDownH);
    dom.bind(_this2.__hue_field, 'touchstart', fieldDownH);

    function fieldDown(e) {

      setSV(e);
      dom.bind(window, 'mousemove', setSV);
      dom.bind(window, 'touchmove', setSV);
      dom.bind(window, 'mouseup', fieldUpSV);
      dom.bind(window, 'touchend', fieldUpSV);

    }

    function fieldDownH(e) {

      setH(e);
      dom.bind(window, 'mousemove', setH);
      dom.bind(window, 'touchmove', setH);
      dom.bind(window, 'mouseup', fieldUpH);
      dom.bind(window, 'touchend', fieldUpH);

    }

    function fieldUpSV() {

      dom.unbind(window, 'mousemove', setSV);
      dom.unbind(window, 'touchmove', setSV);
      dom.unbind(window, 'mouseup', fieldUpSV);
      dom.unbind(window, 'touchend', fieldUpSV);
      onFinish();

    }

    function fieldUpH() {

      dom.unbind(window, 'mousemove', setH);
      dom.unbind(window, 'touchmove', setH);
      dom.unbind(window, 'mouseup', fieldUpH);
      dom.unbind(window, 'touchend', fieldUpH);
      onFinish();

    }

    function onBlur() {

      var i = interpret(this.value);
      if (i !== false) {

        _this.__color.__state = i;
        _this.setValue(_this.__color.toOriginal());

      } else {

        this.value = _this.__color.toString();

      }

    }

    function onFinish() {

      if (_this.__onFinishChange) {

        _this.__onFinishChange.call(_this, _this.__color.toOriginal());

      }

    }

    _this2.__saturation_field.appendChild(valueField);
    _this2.__selector.appendChild(_this2.__field_knob);
    _this2.__selector.appendChild(_this2.__saturation_field);
    _this2.__selector.appendChild(_this2.__hue_field);
    _this2.__hue_field.appendChild(_this2.__hue_knob);
    _this2.domElement.appendChild(_this2.__input);
    _this2.domElement.appendChild(_this2.__selector);
    _this2.updateDisplay();

    function setSV(e) {

      if (e.type.indexOf('touch') === -1) {

        e.preventDefault();

      }
      var fieldRect = _this.__saturation_field.getBoundingClientRect();
      var _ref = e.touches && e.touches[0] || e,
        clientX = _ref.clientX,
        clientY = _ref.clientY;
      var s = (clientX - fieldRect.left) / (fieldRect.right - fieldRect.left);
      var v = 1 - (clientY - fieldRect.top) / (fieldRect.bottom - fieldRect.top);
      if (v > 1) {

        v = 1;

      } else if (v < 0) {

        v = 0;

      }
      if (s > 1) {

        s = 1;

      } else if (s < 0) {

        s = 0;

      }
      _this.__color.v = v;
      _this.__color.s = s;
      _this.setValue(_this.__color.toOriginal());
      return false;

    }

    function setH(e) {

      if (e.type.indexOf('touch') === -1) {

        e.preventDefault();

      }
      var fieldRect = _this.__hue_field.getBoundingClientRect();
      var _ref2 = e.touches && e.touches[0] || e,
        clientY = _ref2.clientY;
      var h = 1 - (clientY - fieldRect.top) / (fieldRect.bottom - fieldRect.top);
      if (h > 1) {

        h = 1;

      } else if (h < 0) {

        h = 0;

      }
      _this.__color.h = h * 360;
      _this.setValue(_this.__color.toOriginal());
      return false;

    }

    return _this2;

  }

  createClass(ColorController, [{
    key: 'updateDisplay',
    value: function updateDisplay() {

      var i = interpret(this.getValue());
      if (i !== false) {

        var mismatch = false;
        Common.each(Color.COMPONENTS, function (component) {

          if (!Common.isUndefined(i[component]) && !Common.isUndefined(this.__color.__state[component]) && i[component] !== this.__color.__state[component]) {

            mismatch = true;
            return {};

          }

        }, this);
        if (mismatch) {

          Common.extend(this.__color.__state, i);

        }

      }
      Common.extend(this.__temp.__state, this.__color.__state);
      this.__temp.a = 1;
      var flip = this.__color.v < 0.5 || this.__color.s > 0.5 ? 255 : 0;
      var _flip = 255 - flip;
      Common.extend(this.__field_knob.style, {
        marginLeft: 100 * this.__color.s - 7 + 'px',
        marginTop: 100 * (1 - this.__color.v) - 7 + 'px',
        backgroundColor: this.__temp.toHexString(),
        border: this.__field_knob_border + 'rgb(' + flip + ',' + flip + ',' + flip + ')'
      });
      this.__hue_knob.style.marginTop = (1 - this.__color.h / 360) * 100 + 'px';
      this.__temp.s = 1;
      this.__temp.v = 1;
      linearGradient(this.__saturation_field, 'left', '#fff', this.__temp.toHexString());
      this.__input.value = this.__color.toString();
      Common.extend(this.__input.style, {
        backgroundColor: this.__color.toHexString(),
        color: 'rgb(' + flip + ',' + flip + ',' + flip + ')',
        textShadow: this.__input_textShadow + 'rgba(' + _flip + ',' + _flip + ',' + _flip + ',.7)'
      });

    }
  }]);
  return ColorController;

}(Controller);
var vendors = ['-moz-', '-o-', '-webkit-', '-ms-', ''];

function linearGradient(elem, x, a, b) {

  elem.style.background = '';
  Common.each(vendors, function (vendor) {

    elem.style.cssText += 'background: ' + vendor + 'linear-gradient(' + x + ', ' + a + ' 0%, ' + b + ' 100%); ';

  });

}

function hueGradient(elem) {

  elem.style.background = '';
  elem.style.cssText += 'background: -moz-linear-gradient(top,  #ff0000 0%, #ff00ff 17%, #0000ff 34%, #00ffff 50%, #00ff00 67%, #ffff00 84%, #ff0000 100%);';
  elem.style.cssText += 'background: -webkit-linear-gradient(top,  #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);';
  elem.style.cssText += 'background: -o-linear-gradient(top,  #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);';
  elem.style.cssText += 'background: -ms-linear-gradient(top,  #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);';
  elem.style.cssText += 'background: linear-gradient(top,  #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);';

}

var css = {
  load: function load(url, indoc) {

    var doc = indoc || document;
    var link = doc.createElement('link');
    link.type = 'text/css';
    link.rel = 'stylesheet';
    link.href = url;
    doc.getElementsByTagName('head')[0].appendChild(link);

  },
  inject: function inject(cssContent, indoc) {

    var doc = indoc || document;
    var injected = document.createElement('style');
    injected.type = 'text/css';
    injected.innerHTML = cssContent;
    var head = doc.getElementsByTagName('head')[0];
    try {

      head.appendChild(injected);

    } catch (e) {
    }

  }
};

var saveDialogContents = "<div id=\"dg-save\" class=\"dg dialogue\">\n\n  Here's the new load parameter for your <code>GUI</code>'s constructor:\n\n  <textarea id=\"dg-new-constructor\"></textarea>\n\n  <div id=\"dg-save-locally\">\n\n    <input id=\"dg-local-storage\" type=\"checkbox\"/> Automatically save\n    values to <code>localStorage</code> on exit.\n\n    <div id=\"dg-local-explain\">The values saved to <code>localStorage</code> will\n      override those passed to <code>dat.GUI</code>'s constructor. This makes it\n      easier to work incrementally, but <code>localStorage</code> is fragile,\n      and your friends may not see the same values you do.\n\n    </div>\n\n  </div>\n\n</div>";

var ControllerFactory = function ControllerFactory(object, property) {

  var initialValue = object[property];
  if (Common.isArray(arguments[2]) || Common.isObject(arguments[2])) {

    return new OptionController(object, property, arguments[2]);

  }
  if (Common.isNumber(initialValue)) {

    if (Common.isNumber(arguments[2]) && Common.isNumber(arguments[3])) {

      if (Common.isNumber(arguments[4])) {

        return new NumberControllerSlider(object, property, arguments[2], arguments[3], arguments[4]);

      }
      return new NumberControllerSlider(object, property, arguments[2], arguments[3]);

    }
    if (Common.isNumber(arguments[4])) {

      return new NumberControllerBox(object, property, {min: arguments[2], max: arguments[3], step: arguments[4]});

    }
    return new NumberControllerBox(object, property, {min: arguments[2], max: arguments[3]});

  }
  if (Common.isString(initialValue)) {

    return new StringController(object, property);

  }
  if (Common.isFunction(initialValue)) {

    return new FunctionController(object, property, '');

  }
  if (Common.isBoolean(initialValue)) {

    return new BooleanController(object, property);

  }
  return null;

};

function requestAnimationFrame(callback) {

  setTimeout(callback, 1000 / 60);

}

var requestAnimationFrame$1 = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || requestAnimationFrame;

var CenteredDiv = function () {

  function CenteredDiv() {

    classCallCheck(this, CenteredDiv);
    this.backgroundElement = document.createElement('div');
    Common.extend(this.backgroundElement.style, {
      backgroundColor: 'rgba(0,0,0,0.8)',
      top: 0,
      left: 0,
      display: 'none',
      zIndex: '1000',
      opacity: 0,
      WebkitTransition: 'opacity 0.2s linear',
      transition: 'opacity 0.2s linear'
    });
    dom.makeFullscreen(this.backgroundElement);
    this.backgroundElement.style.position = 'fixed';
    this.domElement = document.createElement('div');
    Common.extend(this.domElement.style, {
      position: 'fixed',
      display: 'none',
      zIndex: '1001',
      opacity: 0,
      WebkitTransition: '-webkit-transform 0.2s ease-out, opacity 0.2s linear',
      transition: 'transform 0.2s ease-out, opacity 0.2s linear'
    });
    document.body.appendChild(this.backgroundElement);
    document.body.appendChild(this.domElement);
    var _this = this;
    dom.bind(this.backgroundElement, 'click', function () {

      _this.hide();

    });

  }

  createClass(CenteredDiv, [{
    key: 'show',
    value: function show() {

      var _this = this;
      this.backgroundElement.style.display = 'block';
      this.domElement.style.display = 'block';
      this.domElement.style.opacity = 0;
      this.domElement.style.webkitTransform = 'scale(1.1)';
      this.layout();
      Common.defer(function () {

        _this.backgroundElement.style.opacity = 1;
        _this.domElement.style.opacity = 1;
        _this.domElement.style.webkitTransform = 'scale(1)';

      });

    }
  }, {
    key: 'hide',
    value: function hide() {

      var _this = this;
      var hide = function hide() {

        _this.domElement.style.display = 'none';
        _this.backgroundElement.style.display = 'none';
        dom.unbind(_this.domElement, 'webkitTransitionEnd', hide);
        dom.unbind(_this.domElement, 'transitionend', hide);
        dom.unbind(_this.domElement, 'oTransitionEnd', hide);

      };
      dom.bind(this.domElement, 'webkitTransitionEnd', hide);
      dom.bind(this.domElement, 'transitionend', hide);
      dom.bind(this.domElement, 'oTransitionEnd', hide);
      this.backgroundElement.style.opacity = 0;
      this.domElement.style.opacity = 0;
      this.domElement.style.webkitTransform = 'scale(1.1)';

    }
  }, {
    key: 'layout',
    value: function layout() {

      this.domElement.style.left = window.innerWidth / 2 - dom.getWidth(this.domElement) / 2 + 'px';
      this.domElement.style.top = window.innerHeight / 2 - dom.getHeight(this.domElement) / 2 + 'px';

    }
  }]);
  return CenteredDiv;

}();

var styleSheet = ___$insertStyle(".dg ul{list-style:none;margin:0;padding:0;width:100%;clear:both}.dg.ac{position:fixed;top:0;left:0;right:0;height:0;z-index:0}.dg:not(.ac) .main{overflow:hidden}.dg.main{-webkit-transition:opacity .1s linear;-o-transition:opacity .1s linear;-moz-transition:opacity .1s linear;transition:opacity .1s linear}.dg.main.taller-than-window{overflow-y:auto}.dg.main.taller-than-window .close-button{opacity:1;margin-top:-1px;border-top:1px solid #2c2c2c}.dg.main ul.closed .close-button{opacity:1 !important}.dg.main:hover .close-button,.dg.main .close-button.drag{opacity:1}.dg.main .close-button{-webkit-transition:opacity .1s linear;-o-transition:opacity .1s linear;-moz-transition:opacity .1s linear;transition:opacity .1s linear;border:0;line-height:19px;height:20px;cursor:pointer;text-align:center;background-color:#000}.dg.main .close-button.close-top{position:relative}.dg.main .close-button.close-bottom{position:absolute}.dg.main .close-button:hover{background-color:#111}.dg.a{float:right;margin-right:15px;overflow-y:visible}.dg.a.has-save>ul.close-top{margin-top:0}.dg.a.has-save>ul.close-bottom{margin-top:27px}.dg.a.has-save>ul.closed{margin-top:0}.dg.a .save-row{top:0;z-index:1002}.dg.a .save-row.close-top{position:relative}.dg.a .save-row.close-bottom{position:fixed}.dg li{-webkit-transition:height .1s ease-out;-o-transition:height .1s ease-out;-moz-transition:height .1s ease-out;transition:height .1s ease-out;-webkit-transition:overflow .1s linear;-o-transition:overflow .1s linear;-moz-transition:overflow .1s linear;transition:overflow .1s linear}.dg li:not(.folder){cursor:auto;height:27px;line-height:27px;padding:0 4px 0 5px}.dg li.folder{padding:0;border-left:4px solid rgba(0,0,0,0)}.dg li.title{cursor:pointer;margin-left:-4px}.dg .closed li:not(.title),.dg .closed ul li,.dg .closed ul li>*{height:0;overflow:hidden;border:0}.dg .cr{clear:both;padding-left:3px;height:27px;overflow:hidden}.dg .property-name{cursor:default;float:left;clear:left;width:40%;overflow:hidden;text-overflow:ellipsis}.dg .c{float:left;width:60%;position:relative}.dg .c input[type=text]{border:0;margin-top:4px;padding:3px;width:100%;float:right}.dg .has-slider input[type=text]{width:30%;margin-left:0}.dg .slider{float:left;width:66%;margin-left:-5px;margin-right:0;height:19px;margin-top:4px}.dg .slider-fg{height:100%}.dg .c input[type=checkbox]{margin-top:7px}.dg .c select{margin-top:5px}.dg .cr.function,.dg .cr.function .property-name,.dg .cr.function *,.dg .cr.boolean,.dg .cr.boolean *{cursor:pointer}.dg .cr.color{overflow:visible}.dg .selector{display:none;position:absolute;margin-left:-9px;margin-top:23px;z-index:10}.dg .c:hover .selector,.dg .selector.drag{display:block}.dg li.save-row{padding:0}.dg li.save-row .button{display:inline-block;padding:0px 6px}.dg.dialogue{background-color:#222;width:460px;padding:15px;font-size:13px;line-height:15px}#dg-new-constructor{padding:10px;color:#222;font-family:Monaco, monospace;font-size:10px;border:0;resize:none;box-shadow:inset 1px 1px 1px #888;word-wrap:break-word;margin:12px 0;display:block;width:440px;overflow-y:scroll;height:100px;position:relative}#dg-local-explain{display:none;font-size:11px;line-height:17px;border-radius:3px;background-color:#333;padding:8px;margin-top:10px}#dg-local-explain code{font-size:10px}#dat-gui-save-locally{display:none}.dg{color:#eee;font:11px 'Lucida Grande', sans-serif;text-shadow:0 -1px 0 #111}.dg.main::-webkit-scrollbar{width:5px;background:#1a1a1a}.dg.main::-webkit-scrollbar-corner{height:0;display:none}.dg.main::-webkit-scrollbar-thumb{border-radius:5px;background:#676767}.dg li:not(.folder){background:#1a1a1a;border-bottom:1px solid #2c2c2c}.dg li.save-row{line-height:25px;background:#dad5cb;border:0}.dg li.save-row select{margin-left:5px;width:108px}.dg li.save-row .button{margin-left:5px;margin-top:1px;border-radius:2px;font-size:9px;line-height:7px;padding:4px 4px 5px 4px;background:#c5bdad;color:#fff;text-shadow:0 1px 0 #b0a58f;box-shadow:0 -1px 0 #b0a58f;cursor:pointer}.dg li.save-row .button.gears{background:#c5bdad url() 2px 1px no-repeat;height:7px;width:8px}.dg li.save-row .button:hover{background-color:#bab19e;box-shadow:0 -1px 0 #b0a58f}.dg li.folder{border-bottom:0}.dg li.title{padding-left:16px;background:#000 url() 6px 10px no-repeat;cursor:pointer;border-bottom:1px solid rgba(255,255,255,0.2)}.dg .closed li.title{background-image:url()}.dg .cr.boolean{border-left:3px solid #806787}.dg .cr.color{border-left:3px solid}.dg .cr.function{border-left:3px solid #e61d5f}.dg .cr.number{border-left:3px solid #2FA1D6}.dg .cr.number input[type=text]{color:#2FA1D6}.dg .cr.string{border-left:3px solid #1ed36f}.dg .cr.string input[type=text]{color:#1ed36f}.dg .cr.function:hover,.dg .cr.boolean:hover{background:#111}.dg .c input[type=text]{background:#303030;outline:none}.dg .c input[type=text]:hover{background:#3c3c3c}.dg .c input[type=text]:focus{background:#494949;color:#fff}.dg .c .slider{background:#303030;cursor:ew-resize}.dg .c .slider-fg{background:#2FA1D6;max-width:100%}.dg .c .slider:hover{background:#3c3c3c}.dg .c .slider:hover .slider-fg{background:#44abda}\n");

css.inject(styleSheet);
var CSS_NAMESPACE = 'dg';
var HIDE_KEY_CODE = 72;
var CLOSE_BUTTON_HEIGHT = 20;
var DEFAULT_DEFAULT_PRESET_NAME = 'Default';
var SUPPORTS_LOCAL_STORAGE = function () {

  try {

    return !!window.localStorage;

  } catch (e) {

    return false;

  }

}();
var SAVE_DIALOGUE = void 0;
var autoPlaceVirgin = true;
var autoPlaceContainer = void 0;
var hide = false;
var hideableGuis = [];
var GUI = function GUI(pars) {

  var _this = this;
  var params = pars || {};
  this.domElement = document.createElement('div');
  this.__ul = document.createElement('ul');
  this.domElement.appendChild(this.__ul);
  dom.addClass(this.domElement, CSS_NAMESPACE);
  this.__folders = {};
  this.__controllers = [];
  this.__rememberedObjects = [];
  this.__rememberedObjectIndecesToControllers = [];
  this.__listening = [];
  params = Common.defaults(params, {
    closeOnTop: false,
    autoPlace: true,
    width: GUI.DEFAULT_WIDTH
  });
  params = Common.defaults(params, {
    resizable: params.autoPlace,
    hideable: params.autoPlace
  });
  if (!Common.isUndefined(params.load)) {

    if (params.preset) {

      params.load.preset = params.preset;

    }

  } else {

    params.load = {preset: DEFAULT_DEFAULT_PRESET_NAME};

  }
  if (Common.isUndefined(params.parent) && params.hideable) {

    hideableGuis.push(this);

  }
  params.resizable = Common.isUndefined(params.parent) && params.resizable;
  if (params.autoPlace && Common.isUndefined(params.scrollable)) {

    params.scrollable = true;

  }
  var useLocalStorage = SUPPORTS_LOCAL_STORAGE && localStorage.getItem(getLocalStorageHash(this, 'isLocal')) === 'true';
  var saveToLocalStorage = void 0;
  var titleRow = void 0;
  Object.defineProperties(this,
    {
      parent: {
        get: function get$$1() {

          return params.parent;

        }
      },
      scrollable: {
        get: function get$$1() {

          return params.scrollable;

        }
      },
      autoPlace: {
        get: function get$$1() {

          return params.autoPlace;

        }
      },
      closeOnTop: {
        get: function get$$1() {

          return params.closeOnTop;

        }
      },
      preset: {
        get: function get$$1() {

          if (_this.parent) {

            return _this.getRoot().preset;

          }
          return params.load.preset;

        },
        set: function set$$1(v) {

          if (_this.parent) {

            _this.getRoot().preset = v;

          } else {

            params.load.preset = v;

          }
          setPresetSelectIndex(this);
          _this.revert();

        }
      },
      width: {
        get: function get$$1() {

          return params.width;

        },
        set: function set$$1(v) {

          params.width = v;
          setWidth(_this, v);

        }
      },
      name: {
        get: function get$$1() {

          return params.name;

        },
        set: function set$$1(v) {

          params.name = v;
          if (titleRow) {

            titleRow.innerHTML = params.name;

          }

        }
      },
      closed: {
        get: function get$$1() {

          return params.closed;

        },
        set: function set$$1(v) {

          params.closed = v;
          if (params.closed) {

            dom.addClass(_this.__ul, GUI.CLASS_CLOSED);

          } else {

            dom.removeClass(_this.__ul, GUI.CLASS_CLOSED);

          }
          this.onResize();
          if (_this.__closeButton) {

            _this.__closeButton.innerHTML = v ? GUI.TEXT_OPEN : GUI.TEXT_CLOSED;

          }

        }
      },
      load: {
        get: function get$$1() {

          return params.load;

        }
      },
      useLocalStorage: {
        get: function get$$1() {

          return useLocalStorage;

        },
        set: function set$$1(bool) {

          if (SUPPORTS_LOCAL_STORAGE) {

            useLocalStorage = bool;
            if (bool) {

              dom.bind(window, 'unload', saveToLocalStorage);

            } else {

              dom.unbind(window, 'unload', saveToLocalStorage);

            }
            localStorage.setItem(getLocalStorageHash(_this, 'isLocal'), bool);

          }

        }
      }
    });
  if (Common.isUndefined(params.parent)) {

    this.closed = params.closed || false;
    dom.addClass(this.domElement, GUI.CLASS_MAIN);
    dom.makeSelectable(this.domElement, false);
    if (SUPPORTS_LOCAL_STORAGE) {

      if (useLocalStorage) {

        _this.useLocalStorage = true;
        var savedGui = localStorage.getItem(getLocalStorageHash(this, 'gui'));
        if (savedGui) {

          params.load = JSON.parse(savedGui);

        }

      }

    }
    this.__closeButton = document.createElement('div');
    this.__closeButton.innerHTML = GUI.TEXT_CLOSED;
    dom.addClass(this.__closeButton, GUI.CLASS_CLOSE_BUTTON);
    if (params.closeOnTop) {

      dom.addClass(this.__closeButton, GUI.CLASS_CLOSE_TOP);
      this.domElement.insertBefore(this.__closeButton, this.domElement.childNodes[0]);

    } else {

      dom.addClass(this.__closeButton, GUI.CLASS_CLOSE_BOTTOM);
      this.domElement.appendChild(this.__closeButton);

    }
    dom.bind(this.__closeButton, 'click', function () {

      _this.closed = !_this.closed;

    });

  } else {

    if (params.closed === undefined) {

      params.closed = true;

    }
    var titleRowName = document.createTextNode(params.name);
    dom.addClass(titleRowName, 'controller-name');
    titleRow = addRow(_this, titleRowName);
    var onClickTitle = function onClickTitle(e) {

      e.preventDefault();
      _this.closed = !_this.closed;
      return false;

    };
    dom.addClass(this.__ul, GUI.CLASS_CLOSED);
    dom.addClass(titleRow, 'title');
    dom.bind(titleRow, 'click', onClickTitle);
    if (!params.closed) {

      this.closed = false;

    }

  }
  if (params.autoPlace) {

    if (Common.isUndefined(params.parent)) {

      if (autoPlaceVirgin) {

        autoPlaceContainer = document.createElement('div');
        dom.addClass(autoPlaceContainer, CSS_NAMESPACE);
        dom.addClass(autoPlaceContainer, GUI.CLASS_AUTO_PLACE_CONTAINER);
        document.body.appendChild(autoPlaceContainer);
        autoPlaceVirgin = false;

      }
      autoPlaceContainer.appendChild(this.domElement);
      dom.addClass(this.domElement, GUI.CLASS_AUTO_PLACE);

    }
    if (!this.parent) {

      setWidth(_this, params.width);

    }

  }
  this.__resizeHandler = function () {

    _this.onResizeDebounced();

  };
  dom.bind(window, 'resize', this.__resizeHandler);
  dom.bind(this.__ul, 'webkitTransitionEnd', this.__resizeHandler);
  dom.bind(this.__ul, 'transitionend', this.__resizeHandler);
  dom.bind(this.__ul, 'oTransitionEnd', this.__resizeHandler);
  this.onResize();
  if (params.resizable) {

    addResizeHandle(this);

  }
  saveToLocalStorage = function saveToLocalStorage() {

    if (SUPPORTS_LOCAL_STORAGE && localStorage.getItem(getLocalStorageHash(_this, 'isLocal')) === 'true') {

      localStorage.setItem(getLocalStorageHash(_this, 'gui'), JSON.stringify(_this.getSaveObject()));

    }

  };
  this.saveToLocalStorageIfPossible = saveToLocalStorage;

  function resetWidth() {

    var root = _this.getRoot();
    root.width += 1;
    Common.defer(function () {

      root.width -= 1;

    });

  }

  if (!params.parent) {

    resetWidth();

  }

};
GUI.toggleHide = function () {

  hide = !hide;
  Common.each(hideableGuis, function (gui) {

    gui.domElement.style.display = hide ? 'none' : '';

  });

};
GUI.CLASS_AUTO_PLACE = 'a';
GUI.CLASS_AUTO_PLACE_CONTAINER = 'ac';
GUI.CLASS_MAIN = 'main';
GUI.CLASS_CONTROLLER_ROW = 'cr';
GUI.CLASS_TOO_TALL = 'taller-than-window';
GUI.CLASS_CLOSED = 'closed';
GUI.CLASS_CLOSE_BUTTON = 'close-button';
GUI.CLASS_CLOSE_TOP = 'close-top';
GUI.CLASS_CLOSE_BOTTOM = 'close-bottom';
GUI.CLASS_DRAG = 'drag';
GUI.DEFAULT_WIDTH = 245;
GUI.TEXT_CLOSED = 'Close Controls';
GUI.TEXT_OPEN = 'Open Controls';
GUI._keydownHandler = function (e) {

  if (document.activeElement.type !== 'text' && (e.which === HIDE_KEY_CODE || e.keyCode === HIDE_KEY_CODE)) {

    GUI.toggleHide();

  }

};
dom.bind(window, 'keydown', GUI._keydownHandler, false);
Common.extend(GUI.prototype,
  {
    add: function add(object, property) {

      return _add(this, object, property, {
        factoryArgs: Array.prototype.slice.call(arguments, 2)
      });

    },
    addColor: function addColor(object, property) {

      return _add(this, object, property, {
        color: true
      });

    },
    remove: function remove(controller) {

      this.__ul.removeChild(controller.__li);
      this.__controllers.splice(this.__controllers.indexOf(controller), 1);
      var _this = this;
      Common.defer(function () {

        _this.onResize();

      });

    },
    destroy: function destroy() {

      if (this.parent) {

        throw new Error('Only the root GUI should be removed with .destroy(). ' + 'For subfolders, use gui.removeFolder(folder) instead.');

      }
      if (this.autoPlace) {

        autoPlaceContainer.removeChild(this.domElement);

      }
      var _this = this;
      Common.each(this.__folders, function (subfolder) {

        _this.removeFolder(subfolder);

      });
      dom.unbind(window, 'keydown', GUI._keydownHandler, false);
      removeListeners(this);

    },
    addFolder: function addFolder(name) {

      if (this.__folders[name] !== undefined) {

        throw new Error('You already have a folder in this GUI by the' + ' name "' + name + '"');

      }
      var newGuiParams = {name: name, parent: this};
      newGuiParams.autoPlace = this.autoPlace;
      if (this.load &&
        this.load.folders &&
        this.load.folders[name]) {

        newGuiParams.closed = this.load.folders[name].closed;
        newGuiParams.load = this.load.folders[name];

      }
      var gui = new GUI(newGuiParams);
      this.__folders[name] = gui;
      var li = addRow(this, gui.domElement);
      dom.addClass(li, 'folder');
      return gui;

    },
    removeFolder: function removeFolder(folder) {

      this.__ul.removeChild(folder.domElement.parentElement);
      delete this.__folders[folder.name];
      if (this.load &&
        this.load.folders &&
        this.load.folders[folder.name]) {

        delete this.load.folders[folder.name];

      }
      removeListeners(folder);
      var _this = this;
      Common.each(folder.__folders, function (subfolder) {

        folder.removeFolder(subfolder);

      });
      Common.defer(function () {

        _this.onResize();

      });

    },
    open: function open() {

      this.closed = false;

    },
    close: function close() {

      this.closed = true;

    },
    hide: function hide() {

      this.domElement.style.display = 'none';

    },
    show: function show() {

      this.domElement.style.display = '';

    },
    onResize: function onResize() {

      var root = this.getRoot();
      if (root.scrollable) {

        var top = dom.getOffset(root.__ul).top;
        var h = 0;
        Common.each(root.__ul.childNodes, function (node) {

          if (!(root.autoPlace && node === root.__save_row)) {

            h += dom.getHeight(node);

          }

        });
        if (window.innerHeight - top - CLOSE_BUTTON_HEIGHT < h) {

          dom.addClass(root.domElement, GUI.CLASS_TOO_TALL);
          root.__ul.style.height = window.innerHeight - top - CLOSE_BUTTON_HEIGHT + 'px';

        } else {

          dom.removeClass(root.domElement, GUI.CLASS_TOO_TALL);
          root.__ul.style.height = 'auto';

        }

      }
      if (root.__resize_handle) {

        Common.defer(function () {

          root.__resize_handle.style.height = root.__ul.offsetHeight + 'px';

        });

      }
      if (root.__closeButton) {

        root.__closeButton.style.width = root.width + 'px';

      }

    },
    onResizeDebounced: Common.debounce(function () {

      this.onResize();

    }, 50),
    remember: function remember() {

      if (Common.isUndefined(SAVE_DIALOGUE)) {

        SAVE_DIALOGUE = new CenteredDiv();
        SAVE_DIALOGUE.domElement.innerHTML = saveDialogContents;

      }
      if (this.parent) {

        throw new Error('You can only call remember on a top level GUI.');

      }
      var _this = this;
      Common.each(Array.prototype.slice.call(arguments), function (object) {

        if (_this.__rememberedObjects.length === 0) {

          addSaveMenu(_this);

        }
        if (_this.__rememberedObjects.indexOf(object) === -1) {

          _this.__rememberedObjects.push(object);

        }

      });
      if (this.autoPlace) {

        setWidth(this, this.width);

      }

    },
    getRoot: function getRoot() {

      var gui = this;
      while (gui.parent) {

        gui = gui.parent;

      }
      return gui;

    },
    getSaveObject: function getSaveObject() {

      var toReturn = this.load;
      toReturn.closed = this.closed;
      if (this.__rememberedObjects.length > 0) {

        toReturn.preset = this.preset;
        if (!toReturn.remembered) {

          toReturn.remembered = {};

        }
        toReturn.remembered[this.preset] = getCurrentPreset(this);

      }
      toReturn.folders = {};
      Common.each(this.__folders, function (element, key) {

        toReturn.folders[key] = element.getSaveObject();

      });
      return toReturn;

    },
    save: function save() {

      if (!this.load.remembered) {

        this.load.remembered = {};

      }
      this.load.remembered[this.preset] = getCurrentPreset(this);
      markPresetModified(this, false);
      this.saveToLocalStorageIfPossible();

    },
    saveAs: function saveAs(presetName) {

      if (!this.load.remembered) {

        this.load.remembered = {};
        this.load.remembered[DEFAULT_DEFAULT_PRESET_NAME] = getCurrentPreset(this, true);

      }
      this.load.remembered[presetName] = getCurrentPreset(this);
      this.preset = presetName;
      addPresetOption(this, presetName, true);
      this.saveToLocalStorageIfPossible();

    },
    revert: function revert(gui) {

      Common.each(this.__controllers, function (controller) {

        if (!this.getRoot().load.remembered) {

          controller.setValue(controller.initialValue);

        } else {

          recallSavedValue(gui || this.getRoot(), controller);

        }
        if (controller.__onFinishChange) {

          controller.__onFinishChange.call(controller, controller.getValue());

        }

      }, this);
      Common.each(this.__folders, function (folder) {

        folder.revert(folder);

      });
      if (!gui) {

        markPresetModified(this.getRoot(), false);

      }

    },
    listen: function listen(controller) {

      var init = this.__listening.length === 0;
      this.__listening.push(controller);
      if (init) {

        updateDisplays(this.__listening);

      }

    },
    updateDisplay: function updateDisplay() {

      Common.each(this.__controllers, function (controller) {

        controller.updateDisplay();

      });
      Common.each(this.__folders, function (folder) {

        folder.updateDisplay();

      });

    }
  });

function addRow(gui, newDom, liBefore) {

  var li = document.createElement('li');
  if (newDom) {

    li.appendChild(newDom);

  }
  if (liBefore) {

    gui.__ul.insertBefore(li, liBefore);

  } else {

    gui.__ul.appendChild(li);

  }
  gui.onResize();
  return li;

}

function removeListeners(gui) {

  dom.unbind(window, 'resize', gui.__resizeHandler);
  if (gui.saveToLocalStorageIfPossible) {

    dom.unbind(window, 'unload', gui.saveToLocalStorageIfPossible);

  }

}

function markPresetModified(gui, modified) {

  var opt = gui.__preset_select[gui.__preset_select.selectedIndex];
  if (modified) {

    opt.innerHTML = opt.value + '*';

  } else {

    opt.innerHTML = opt.value;

  }

}

function augmentController(gui, li, controller) {

  controller.__li = li;
  controller.__gui = gui;
  Common.extend(controller, {
    options: function options(_options) {

      if (arguments.length > 1) {

        var nextSibling = controller.__li.nextElementSibling;
        controller.remove();
        return _add(gui, controller.object, controller.property, {
          before: nextSibling,
          factoryArgs: [Common.toArray(arguments)]
        });

      }
      if (Common.isArray(_options) || Common.isObject(_options)) {

        var _nextSibling = controller.__li.nextElementSibling;
        controller.remove();
        return _add(gui, controller.object, controller.property, {
          before: _nextSibling,
          factoryArgs: [_options]
        });

      }

    },
    name: function name(_name) {

      controller.__li.firstElementChild.firstElementChild.innerHTML = _name;
      return controller;

    },
    listen: function listen() {

      controller.__gui.listen(controller);
      return controller;

    },
    remove: function remove() {

      controller.__gui.remove(controller);
      return controller;

    }
  });
  if (controller instanceof NumberControllerSlider) {

    var box = new NumberControllerBox(controller.object, controller.property, {min: controller.__min, max: controller.__max, step: controller.__step});
    Common.each(['updateDisplay', 'onChange', 'onFinishChange', 'step', 'min', 'max'], function (method) {

      var pc = controller[method];
      var pb = box[method];
      controller[method] = box[method] = function () {

        var args = Array.prototype.slice.call(arguments);
        pb.apply(box, args);
        return pc.apply(controller, args);

      };

    });
    dom.addClass(li, 'has-slider');
    controller.domElement.insertBefore(box.domElement, controller.domElement.firstElementChild);

  } else if (controller instanceof NumberControllerBox) {

    var r = function r(returned) {

      if (Common.isNumber(controller.__min) && Common.isNumber(controller.__max)) {

        var oldName = controller.__li.firstElementChild.firstElementChild.innerHTML;
        var wasListening = controller.__gui.__listening.indexOf(controller) > -1;
        controller.remove();
        var newController = _add(gui, controller.object, controller.property, {
          before: controller.__li.nextElementSibling,
          factoryArgs: [controller.__min, controller.__max, controller.__step]
        });
        newController.name(oldName);
        if (wasListening) newController.listen();
        return newController;

      }
      return returned;

    };
    controller.min = Common.compose(r, controller.min);
    controller.max = Common.compose(r, controller.max);

  } else if (controller instanceof BooleanController) {

    dom.bind(li, 'click', function () {

      dom.fakeEvent(controller.__checkbox, 'click');

    });
    dom.bind(controller.__checkbox, 'click', function (e) {

      e.stopPropagation();

    });

  } else if (controller instanceof FunctionController) {

    dom.bind(li, 'click', function () {

      dom.fakeEvent(controller.__button, 'click');

    });
    dom.bind(li, 'mouseover', function () {

      dom.addClass(controller.__button, 'hover');

    });
    dom.bind(li, 'mouseout', function () {

      dom.removeClass(controller.__button, 'hover');

    });

  } else if (controller instanceof ColorController) {

    dom.addClass(li, 'color');
    controller.updateDisplay = Common.compose(function (val) {

      li.style.borderLeftColor = controller.__color.toString();
      return val;

    }, controller.updateDisplay);
    controller.updateDisplay();

  }
  controller.setValue = Common.compose(function (val) {

    if (gui.getRoot().__preset_select && controller.isModified()) {

      markPresetModified(gui.getRoot(), true);

    }
    return val;

  }, controller.setValue);

}

function recallSavedValue(gui, controller) {

  var root = gui.getRoot();
  var matchedIndex = root.__rememberedObjects.indexOf(controller.object);
  if (matchedIndex !== -1) {

    var controllerMap = root.__rememberedObjectIndecesToControllers[matchedIndex];
    if (controllerMap === undefined) {

      controllerMap = {};
      root.__rememberedObjectIndecesToControllers[matchedIndex] = controllerMap;

    }
    controllerMap[controller.property] = controller;
    if (root.load && root.load.remembered) {

      var presetMap = root.load.remembered;
      var preset = void 0;
      if (presetMap[gui.preset]) {

        preset = presetMap[gui.preset];

      } else if (presetMap[DEFAULT_DEFAULT_PRESET_NAME]) {

        preset = presetMap[DEFAULT_DEFAULT_PRESET_NAME];

      } else {

        return;

      }
      if (preset[matchedIndex] && preset[matchedIndex][controller.property] !== undefined) {

        var value = preset[matchedIndex][controller.property];
        controller.initialValue = value;
        controller.setValue(value);

      }

    }

  }

}

function _add(gui, object, property, params) {

  if (object[property] === undefined) {

    throw new Error('Object "' + object + '" has no property "' + property + '"');

  }
  var controller = void 0;
  if (params.color) {

    controller = new ColorController(object, property);

  } else {

    var factoryArgs = [object, property].concat(params.factoryArgs);
    controller = ControllerFactory.apply(gui, factoryArgs);

  }
  if (params.before instanceof Controller) {

    params.before = params.before.__li;

  }
  recallSavedValue(gui, controller);
  dom.addClass(controller.domElement, 'c');
  var name = document.createElement('span');
  dom.addClass(name, 'property-name');
  name.innerHTML = controller.property;
  var container = document.createElement('div');
  container.appendChild(name);
  container.appendChild(controller.domElement);
  var li = addRow(gui, container, params.before);
  dom.addClass(li, GUI.CLASS_CONTROLLER_ROW);
  if (controller instanceof ColorController) {

    dom.addClass(li, 'color');

  } else {

    dom.addClass(li, _typeof(controller.getValue()));

  }
  augmentController(gui, li, controller);
  gui.__controllers.push(controller);
  return controller;

}

function getLocalStorageHash(gui, key) {

  return document.location.href + '.' + key;

}

function addPresetOption(gui, name, setSelected) {

  var opt = document.createElement('option');
  opt.innerHTML = name;
  opt.value = name;
  gui.__preset_select.appendChild(opt);
  if (setSelected) {

    gui.__preset_select.selectedIndex = gui.__preset_select.length - 1;

  }

}

function showHideExplain(gui, explain) {

  explain.style.display = gui.useLocalStorage ? 'block' : 'none';

}

function addSaveMenu(gui) {

  var div = gui.__save_row = document.createElement('li');
  dom.addClass(gui.domElement, 'has-save');
  gui.__ul.insertBefore(div, gui.__ul.firstChild);
  dom.addClass(div, 'save-row');
  var gears = document.createElement('span');
  gears.innerHTML = '&nbsp;';
  dom.addClass(gears, 'button gears');
  var button = document.createElement('span');
  button.innerHTML = 'Save';
  dom.addClass(button, 'button');
  dom.addClass(button, 'save');
  var button2 = document.createElement('span');
  button2.innerHTML = 'New';
  dom.addClass(button2, 'button');
  dom.addClass(button2, 'save-as');
  var button3 = document.createElement('span');
  button3.innerHTML = 'Revert';
  dom.addClass(button3, 'button');
  dom.addClass(button3, 'revert');
  var select = gui.__preset_select = document.createElement('select');
  if (gui.load && gui.load.remembered) {

    Common.each(gui.load.remembered, function (value, key) {

      addPresetOption(gui, key, key === gui.preset);

    });

  } else {

    addPresetOption(gui, DEFAULT_DEFAULT_PRESET_NAME, false);

  }
  dom.bind(select, 'change', function () {

    for (var index = 0; index < gui.__preset_select.length; index++) {

      gui.__preset_select[index].innerHTML = gui.__preset_select[index].value;

    }
    gui.preset = this.value;

  });
  div.appendChild(select);
  div.appendChild(gears);
  div.appendChild(button);
  div.appendChild(button2);
  div.appendChild(button3);
  if (SUPPORTS_LOCAL_STORAGE) {

    var explain = document.getElementById('dg-local-explain');
    var localStorageCheckBox = document.getElementById('dg-local-storage');
    var saveLocally = document.getElementById('dg-save-locally');
    saveLocally.style.display = 'block';
    if (localStorage.getItem(getLocalStorageHash(gui, 'isLocal')) === 'true') {

      localStorageCheckBox.setAttribute('checked', 'checked');

    }
    showHideExplain(gui, explain);
    dom.bind(localStorageCheckBox, 'change', function () {

      gui.useLocalStorage = !gui.useLocalStorage;
      showHideExplain(gui, explain);

    });

  }
  var newConstructorTextArea = document.getElementById('dg-new-constructor');
  dom.bind(newConstructorTextArea, 'keydown', function (e) {

    if (e.metaKey && (e.which === 67 || e.keyCode === 67)) {

      SAVE_DIALOGUE.hide();

    }

  });
  dom.bind(gears, 'click', function () {

    newConstructorTextArea.innerHTML = JSON.stringify(gui.getSaveObject(), undefined, 2);
    SAVE_DIALOGUE.show();
    newConstructorTextArea.focus();
    newConstructorTextArea.select();

  });
  dom.bind(button, 'click', function () {

    gui.save();

  });
  dom.bind(button2, 'click', function () {

    var presetName = prompt('Enter a new preset name.');
    if (presetName) {

      gui.saveAs(presetName);

    }

  });
  dom.bind(button3, 'click', function () {

    gui.revert();

  });

}

function addResizeHandle(gui) {

  var pmouseX = void 0;
  gui.__resize_handle = document.createElement('div');
  Common.extend(gui.__resize_handle.style, {
    width: '6px',
    marginLeft: '-3px',
    height: '200px',
    cursor: 'ew-resize',
    position: 'absolute'
  });

  function drag(e) {

    e.preventDefault();
    gui.width += pmouseX - e.clientX;
    gui.onResize();
    pmouseX = e.clientX;
    return false;

  }

  function dragStop() {

    dom.removeClass(gui.__closeButton, GUI.CLASS_DRAG);
    dom.unbind(window, 'mousemove', drag);
    dom.unbind(window, 'mouseup', dragStop);

  }

  function dragStart(e) {

    e.preventDefault();
    pmouseX = e.clientX;
    dom.addClass(gui.__closeButton, GUI.CLASS_DRAG);
    dom.bind(window, 'mousemove', drag);
    dom.bind(window, 'mouseup', dragStop);
    return false;

  }

  dom.bind(gui.__resize_handle, 'mousedown', dragStart);
  dom.bind(gui.__closeButton, 'mousedown', dragStart);
  gui.domElement.insertBefore(gui.__resize_handle, gui.domElement.firstElementChild);

}

function setWidth(gui, w) {

  gui.domElement.style.width = w + 'px';
  if (gui.__save_row && gui.autoPlace) {

    gui.__save_row.style.width = w + 'px';

  }
  if (gui.__closeButton) {

    gui.__closeButton.style.width = w + 'px';

  }

}

function getCurrentPreset(gui, useInitialValues) {

  var toReturn = {};
  Common.each(gui.__rememberedObjects, function (val, index) {

    var savedValues = {};
    var controllerMap = gui.__rememberedObjectIndecesToControllers[index];
    Common.each(controllerMap, function (controller, property) {

      savedValues[property] = useInitialValues ? controller.initialValue : controller.getValue();

    });
    toReturn[index] = savedValues;

  });
  return toReturn;

}

function setPresetSelectIndex(gui) {

  for (var index = 0; index < gui.__preset_select.length; index++) {

    if (gui.__preset_select[index].value === gui.preset) {

      gui.__preset_select.selectedIndex = index;

    }

  }

}

function updateDisplays(controllerArray) {

  if (controllerArray.length !== 0) {

    requestAnimationFrame$1.call(window, function () {

      updateDisplays(controllerArray);

    });

  }
  Common.each(controllerArray, function (c) {

    c.updateDisplay();

  });

}

var color = {
  Color: Color,
  math: ColorMath,
  interpret: interpret
};
var controllers = {
  Controller: Controller,
  BooleanController: BooleanController,
  OptionController: OptionController,
  StringController: StringController,
  NumberController: NumberController,
  NumberControllerBox: NumberControllerBox,
  NumberControllerSlider: NumberControllerSlider,
  FunctionController: FunctionController,
  ColorController: ColorController
};
var dom$1 = {dom: dom};
var gui = {GUI: GUI};
var GUI$1 = GUI;
var index = {
  color: color,
  controllers: controllers,
  dom: dom$1,
  gui: gui,
  GUI: GUI$1
};

export {color, controllers, dom$1 as dom, gui, GUI$1 as GUI};
export default index;
